// 递归遍历结构体并设置空数据为初始值 便于返回json时候为空不返回,因为nil会被返回null
func SetEmptyFieldsToZero(root interface{}) {
// 获取根节点的反射值
rv := reflect.ValueOf(root)
// 检查根节点是否为指针类型,如果是,获取其指向的值
if rv.Kind() == reflect.Ptr {
rv = rv.Elem()
}
// 检查根节点是否为结构体类型
if rv.Kind() != reflect.Struct {
//fmt.Println("Input is not a struct")
return
}
// 遍历结构体的字段
for i := 0; i < rv.NumField(); i++ {
fieldValue := rv.Field(i)
// 检查字段的类型
switch fieldValue.Kind() {
case reflect.Struct:
// 如果字段是结构体类型,则递归调用本方法
SetEmptyFieldsToZero(fieldValue.Addr().Interface())
case reflect.Ptr:
// 如果字段是指针类型
if fieldValue.IsNil() {
// 如果指针为空,则创建一个新的实例并设置为字段的零值
fieldValue.Set(reflect.New(fieldValue.Type().Elem()))
} else {
// 如果指针不为空,则解引用指针并递归调用本方法
SetEmptyFieldsToZero(fieldValue.Interface())
}
// 检查指针所指向的结构体中的字段是否都是零值,如果是,则将指针字段设置为 nil
if fieldValue.Elem().Kind() == reflect.Struct {
subStruct := fieldValue.Elem()
isSubStructZero := true
for j := 0; j < subStruct.NumField(); j++ {
if !reflect.DeepEqual(subStruct.Field(j).Interface(), reflect.Zero(subStruct.Field(j).Type()).Interface()) {
isSubStructZero = false
break
}
}
if isSubStructZero {
fieldValue.Set(reflect.Zero(fieldValue.Type()))
}
}
case reflect.Slice:
// 如果字段是切片类型
if fieldValue.IsNil() {
// 如果切片为空,则创建一个新的实例并设置为字段的零值
fieldValue.Set(reflect.MakeSlice(fieldValue.Type(), 0, 0))
} else {
// 如果切片不为空,则遍历切片的每个元素并递归调用本方法
for j := 0; j < fieldValue.Len(); j++ {
SetEmptyFieldsToZero(fieldValue.Index(j).Addr().Interface())
}
}
default:
// 对于其他类型的字段,如果其值为空,则设置为零值
if reflect.DeepEqual(fieldValue.Interface(), reflect.Zero(fieldValue.Type()).Interface()) {
fieldValue.Set(reflect.Zero(fieldValue.Type()))
}
}
}
}
共有 0 - golang 常用工具方法